iT邦幫忙

2021 iThome 鐵人賽

DAY 5
0
自我挑戰組

前端補給站,每天一個知識點系列 第 5

Day04【JS】Promise、Async 和 Await

  • 分享至 

  • xImage
  •  

Promise

  • 保證執行之後才會做什麼事情
  • 對於「未來的值」的獨立封裝

狀態

pending:尚未被fulfilled或rejected
fulfilled:成功完成 onFulfilled/resolve
rejected:操作失敗 onRejected/reject

const delay = (s) => {
  return new Promise(resolve => {
    setTimeout(resolve,s); 
  });
};

delay().then(() => {
  console.log(1);     // 顯示 1
  return delay(1000); // 延遲ㄧ秒
}).then(() => {
  console.log(2);     // 顯示 2
  return delay(2000); // 延遲二秒
}).then(() => {
  console.log(3);     // 顯示 3
});

處理成功&失敗

delay()
    .then((response) => {
        if(response.result === 'success') {
            console.log('Success!')
        } else if(response.result === 'failure') {
            throw new Error('Whoops!');
        }
    })
    .catch((error) => {
        // ...
        console.log(error);
    });

Async 和 Await(ES6+)

  • async/await 基本上是一種把 Promise 的重新包裝使用語法糖
  • await 一定要運行在 async function 內
~async function{
  const delay = (s) => {
    return new Promise(function(resolve){  // 回傳一個 promise
      setTimeout(resolve,s);               // 等待多少秒之後 resolve()
    });
  };

  console.log(1);      // 顯示 1
  await delay(1000);   // 延遲ㄧ秒
  console.log(2);      // 顯示 2
  await delay(2000);   // 延遲二秒
  console.log(3);      // 顯示 3
}();

開頭的「~」表示直接執行這個 function,留意結尾有「()」表示立即執行

搭配 fetch 使用

fetch 最後回傳的是 promise,很適合透過 async 和 await 操作

~async function(){
    console.log('開始抓氣象');       // 先顯示「開始抓氣象」
    await fetch('氣象局 json 網址')  // 帶有 await 的 fetch
    .then(res => {
        return res.json();
    }).then(result => {
        let city = result.cwbopendata.location[14].parameter[0].parameterValue;
        let temp = result.cwbopendata.location[14].weatherElement[3].elementValue.value;
        console.log(`${city}的氣溫為 ${temp} 度 C`); 
    });
    console.log('總算結束了');       // 抓完氣象之後再顯示「總算結束了」
}();

Yield

用以暫停和恢復一個生成器函式(generator function)

function* foo() {
  for (let i = 1; i <= 3; i++) {
    let x = yield `再等一下,i = ${i}`;
    console.log(x);
  }
}

setTimeout(() => {
  console.log('終於輪到我了');
}, 1);

var a = foo();
console.log(a); // foo {<closed>}

var b = a.next();
console.log(b); // {value: "再等一下,i = 1", done: false}

var c = a.next();
console.log(c); // {value: "再等一下,i = 2", done: false}

var d = a.next();
console.log(d); // {value: "再等一下,i = 3", done: false}

var e = a.next();
console.log(e); // {value: undefined, done: true}

// 終於輪到我了

Promise.all

await Promise.all([task1(), task2(), task3()]);

當任一個陣列成員 rejected 則整個 Promise.all 立刻被拒絕。

Promise.allSettled

const responses = await Promise.allSettled([task1(), task2(), task3()]);
if(responses.every(response => response.result === 'success')) {
    console.log('Success!')
} else if(responses.some(response => response.result === 'failure')) { 
    responses.forEach(error => {
        console.log('error: ', error);
    });
}

絕對不會被 rejected,因此邏輯可以直接寫在 then 或是不用寫 try catch,需另外解析array內的resolved與rejected

參考資料


上一篇
Day03【JS】立即呼叫函式 IIFE
下一篇
Day05【Web】Websocket、Polling 與 SSE
系列文
前端補給站,每天一個知識點30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言